home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / mega src / Source / odoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-17  |  11.4 KB  |  464 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     odoc.c
  4.         
  5.     Copyright (c) 1993,1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #include <appleevents.h>
  16. #include <processes.h>
  17. #include <Aliases.h>
  18. #include <GestaltEqu.h>
  19.  
  20. #include "nshc.h"
  21.  
  22. #include "arg_utl.proto.h"
  23. #include "str_utl.proto.h"
  24. #include "fss_utl.proto.h"
  25. #include "nshc_utl.proto.h"
  26.  
  27. /* ======================================== */
  28.  
  29. // prototypes
  30.  
  31. int        Pre7( void );
  32. int        is_it_running( OSType targetSignature );
  33. OSErr    odoc( int gotFSSpec, FSSpec *doc_fss, OSType app_sig, t_nshc_calls *nshc_calls );
  34. int        SearchOne( short vol, OSType creator, FSSpec *app_fss );
  35. int        SearchAllButOne( Boolean remote_search, OSType creator, FSSpec *doc_fss, FSSpec *app_fss );
  36. int        find_app( OSType creator, FSSpec *doc_fss, FSSpec *app_fss );
  37. OSErr    launch( int gotFSSpec, FSSpec *launchApp, FSSpec *launchDoc, t_nshc_calls *nshc_calls );
  38.  
  39. /* ======================================== */
  40.  
  41. // return true if 'sysv' is previous to 7.0
  42.  
  43. int    Pre7( void )
  44. {
  45.     OSErr    error;
  46.     long    response;
  47.     
  48.     if ( error = Gestalt( 'sysv', &response ) )
  49.         return(true);
  50.         
  51.     if ( response < 0x700 )
  52.         return(true);
  53.     else
  54.         return(false);
  55. }
  56.  
  57. /* ======================================== */
  58.  
  59. int    is_it_running( OSType targetSignature )
  60. {
  61.     Str255                    name;
  62.     ProcessSerialNumber        psn_p;
  63.     ProcessInfoRec          pi;
  64.             
  65.     pi.processName       = name;
  66.     pi.processInfoLength = sizeof(pi);
  67.     pi.processAppSpec    = NULL;
  68.     
  69.     psn_p.highLongOfPSN = 0;
  70.     psn_p.lowLongOfPSN  = kNoProcess;
  71.         
  72.     while(!GetNextProcess(&psn_p))
  73.         if(!GetProcessInformation(&psn_p,&pi))
  74.             if ( pi.processSignature == targetSignature )
  75.                 return( 1 );
  76.  
  77.     return( 0 );
  78. }
  79.  
  80. /* ======================================== */
  81.  
  82. OSErr odoc( int gotFSSpec, FSSpec *doc_fss, OSType app_sig, t_nshc_calls *nshc_calls )
  83. {
  84.     OSErr            myErr;
  85.     FInfo            finfo;
  86.     int                appRunning;
  87.     AEDesc            appDesc;
  88.     AliasHandle        docAlias;
  89.     AppleEvent        openAE;
  90.     AppleEvent        replyAE;
  91.     AEDescList        docList;
  92.     
  93.     // initialize
  94.     
  95.     openAE.dataHandle = nil;
  96.     replyAE.dataHandle = nil;
  97.     appDesc.dataHandle = nil;
  98.     docList.dataHandle = nil;
  99.     
  100.     docAlias = nil;
  101.             
  102.     // see if the app is running
  103.     
  104.     appRunning = is_it_running( app_sig );
  105.     
  106.     if (!appRunning) {
  107.         nshc_calls->NSH_putStr_err("\podoc: Target process is not running\r");
  108.         return(1);
  109.         }
  110.  
  111.     myErr = AECreateDesc(typeApplSignature,
  112.                          (Ptr)&app_sig,
  113.                          sizeof(app_sig),
  114.                          &appDesc);
  115.     if (myErr) goto Cleanup;    
  116.                          
  117.     myErr = NewAlias(nil,doc_fss,&docAlias);
  118.     if (myErr) goto Cleanup;    
  119.  
  120.     myErr = AECreateAppleEvent(kCoreEventClass,
  121.                                kAEOpenDocuments,
  122.                                &appDesc,
  123.                                kAutoGenerateReturnID,
  124.                                kAnyTransactionID,
  125.                                &openAE);
  126.     if (myErr) goto Cleanup;    
  127.  
  128.     myErr = AECreateList(nil,0,false,&docList);
  129.     if (myErr) goto Cleanup;    
  130.  
  131.     HLock(docAlias);
  132.     myErr = AEPutPtr(&docList,
  133.                      0,
  134.                      typeAlias,
  135.                      (Ptr)*docAlias,
  136.                      sizeof(AliasHandle)+(**docAlias).aliasSize);
  137.     HUnlock(docAlias);
  138.     if (myErr) goto Cleanup;    
  139.  
  140.     myErr = AEPutParamDesc(&openAE,keyDirectObject,&docList);
  141.     if (myErr) goto Cleanup;
  142.     
  143.     myErr = AESend(&openAE,&replyAE,kAENoReply,kAENormalPriority,kAEDefaultTimeout,nil,nil);
  144.         
  145. Cleanup:
  146.  
  147.     if (myErr) nshc_calls->NSH_putStr_err("\podoc: Message could not be sent.\r");
  148.     
  149.     if (docList.dataHandle) AEDisposeDesc(&docList);
  150.     if (openAE.dataHandle) AEDisposeDesc(&openAE);
  151.     if (replyAE.dataHandle) AEDisposeDesc(&replyAE);
  152.     if (appDesc.dataHandle) AEDisposeDesc(&appDesc);
  153.     
  154.     if (docAlias) DisposHandle(docAlias);
  155.     
  156.     return(myErr);
  157. }
  158.  
  159. /* ======================================== */
  160.  
  161. OSErr launch( int gotFSSpec, FSSpec *launchApp, FSSpec *launchDoc, t_nshc_calls *nshc_calls )
  162. {    
  163.     AEDesc                docDesc;
  164.     AEDesc                parmDesc;
  165.     AEDesc                adrDesc;
  166.     AEDescList            docList;
  167.     AliasHandle            docAlias;
  168.     AppleEvent            fakeEvent;
  169.     AppParametersPtr    docParm;
  170.     LaunchParamBlockRec    launchThis;
  171.     OSErr                myErr;
  172.     ProcessSerialNumber myPSN;
  173.     
  174.     // initialize
  175.     
  176.     docDesc.dataHandle = nil;
  177.     parmDesc.dataHandle = nil;
  178.     adrDesc.dataHandle = nil;
  179.     docList.dataHandle = nil;
  180.     docAlias = nil;
  181.     fakeEvent.dataHandle = nil;
  182.  
  183.     GetCurrentProcess(&myPSN);        // used to initialize new AE things
  184.     
  185.     // create the address desc for the event
  186.     
  187.     myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&myPSN, sizeof(ProcessSerialNumber), &adrDesc);
  188.     if (myErr) goto Cleanup;
  189.  
  190.     // stuff it in my launch parameter block
  191.     
  192.     launchThis.launchAppSpec = launchApp;
  193.     
  194.     if (launchDoc) {
  195.         
  196.         // create an apple event for "open doc"
  197.         myErr = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &adrDesc, kAutoGenerateReturnID, kAnyTransactionID, &fakeEvent);
  198.         if (myErr) goto Cleanup;
  199.  
  200.         // create a list to hold the doc alias
  201.         myErr = AECreateList(nil, 0, false, &docList);
  202.         if (myErr) goto Cleanup;
  203.     
  204.         // ae needs an alias to the doc
  205.         myErr = NewAlias(nil, launchDoc, &docAlias);
  206.         if (myErr) goto Cleanup;
  207.  
  208.         // and a descriptor for the alias
  209.         HLock((Handle)docAlias);
  210.         myErr = AECreateDesc(typeAlias, (Ptr)*docAlias, GetHandleSize((Handle)docAlias), &docDesc);
  211.         HUnlock((Handle)docAlias);
  212.         if (myErr) goto Cleanup;
  213.     
  214.         // the descriptor goes in the list
  215.         myErr = AEPutDesc(&docList, 0, &docDesc);
  216.         if (myErr) goto Cleanup;
  217.         
  218.         // and the list goes into the event
  219.         myErr = AEPutParamDesc(&fakeEvent, keyDirectObject, &docList);
  220.         if (myErr) goto Cleanup;
  221.     
  222.         // but the fake event is REALLY a parameter!
  223.         myErr = AECoerceDesc(&fakeEvent, typeAppParameters, &parmDesc);
  224.         if (myErr) goto Cleanup;
  225.         
  226.         docParm = (AppParametersPtr)*(parmDesc.dataHandle);
  227.         }
  228.     else
  229.         docParm = nil;
  230.     
  231.     // stuff the LaunchParamBlockRec and send it
  232.     
  233.     HLock((Handle)fakeEvent.dataHandle);
  234.     
  235.     launchThis.launchAppParameters = docParm;
  236.     launchThis.launchBlockID = extendedBlock;
  237.     launchThis.launchEPBLength = extendedBlockLen;
  238.     launchThis.launchFileFlags = 0;
  239.     launchThis.launchControlFlags = launchContinue + launchNoFileFlags;
  240.     
  241.     myErr = LaunchApplication(&launchThis);
  242.     
  243.     HUnlock((Handle)fakeEvent.dataHandle);
  244.     
  245. Cleanup:
  246.  
  247.     if (myErr) nshc_calls->NSH_putStr_err("\plaunch: Message could not be sent.\r");
  248.     
  249.     if ( docDesc.dataHandle ) AEDisposeDesc(&docDesc);
  250.     if ( parmDesc.dataHandle ) AEDisposeDesc(&parmDesc);
  251.     if ( adrDesc.dataHandle ) AEDisposeDesc(&adrDesc);
  252.     if ( docList.dataHandle ) AEDisposeDesc(&docDesc);
  253.     if ( fakeEvent.dataHandle )AEDisposeDesc(&fakeEvent);
  254.  
  255.     if ( docAlias ) DisposeHandle((Handle)docAlias);
  256.  
  257.     return(myErr);
  258. }
  259.  
  260. /* ======================================== */
  261.  
  262. int SearchOne( short vol, OSType creator, FSSpec *app_fss )
  263. {
  264.     DTPBRec        desktopParams;
  265.     OSErr        myErr;
  266.     int            found;
  267.     
  268.     found = 0;
  269.  
  270.     desktopParams.ioVRefNum = vol;
  271.     desktopParams.ioNamePtr = nil;
  272.     
  273.     myErr = PBDTGetPath(&desktopParams);
  274.     
  275.     if (!myErr && (desktopParams.ioDTRefNum != 0)) {
  276.     
  277.         desktopParams.ioIndex = 0;
  278.         desktopParams.ioFileCreator = creator;
  279.         desktopParams.ioNamePtr = app_fss->name;
  280.         
  281.         myErr = PBDTGetAPPLSync(&desktopParams);
  282.         
  283.         if (!myErr) {
  284.         
  285.             // okay, found it; fill in the application file spec
  286.             // and set the flag indicating we're done
  287.             
  288.             app_fss->parID = desktopParams.ioAPPLParID;
  289.             app_fss->vRefNum = desktopParams.ioVRefNum;
  290.             found = 1;
  291.             
  292.         }
  293.     }
  294.     
  295.     return( found );    
  296. }
  297.  
  298. int SearchAllButOne( Boolean remote_search, OSType creator, FSSpec *doc_fss, FSSpec *app_fss )
  299. {
  300.     HParamBlockRec            hfsParams;
  301.     FInfo                    documentFInfo;
  302.     short                    volumeIndex;
  303.     int                        found;
  304.     GetVolParmsInfoBuffer    volumeInfoBuffer;
  305.     OSErr                    myErr;
  306.     
  307.     found = 0;
  308.     volumeIndex = 0;
  309.     
  310.     while (!found) {
  311.         
  312.         volumeIndex++;
  313.             
  314.         // convert the volumeIndex into a vRefNum
  315.         
  316.         hfsParams.volumeParam.ioNamePtr = nil;
  317.         hfsParams.volumeParam.ioVRefNum = 0;
  318.         hfsParams.volumeParam.ioVolIndex = volumeIndex;
  319.         myErr = PBHGetVInfoSync(&hfsParams);
  320.         
  321.         // a nsvErr indicates that the current pass is over
  322.         if (myErr) return( 0 );
  323.         
  324.         // since we handled the document volume during the documentPass,
  325.         // skip it if we have hit that volume again
  326.         
  327.         if (hfsParams.volumeParam.ioVRefNum != doc_fss->vRefNum) {
  328.         
  329.             // call GetVolParms to determine if this volume is a server
  330.             // (a remote volume)
  331.             
  332.             hfsParams.ioParam.ioBuffer = (Ptr) &volumeInfoBuffer;
  333.             hfsParams.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
  334.             myErr = PBHGetVolParmsSync(&hfsParams);
  335.             
  336.             if (myErr) return( 0 );
  337.             
  338.             // if the vMServerAdr field of the volume information buffer
  339.             // is zero, this is a local volume; skip this volume
  340.             // if it's local on a remote pass or remote on a local pass
  341.             
  342.             if ( ( volumeInfoBuffer.vMServerAdr == 0 ) != remote_search )
  343.                 found = SearchOne( hfsParams.volumeParam.ioVRefNum, creator, app_fss );
  344.                 
  345.             }
  346.                 
  347.     }
  348.     
  349.     return( found );
  350. }
  351.  
  352. /* ======================================== */
  353.  
  354. int find_app( OSType creator, FSSpec *doc_fss, FSSpec *app_fss )
  355. {
  356.     OSErr    found;
  357.     
  358.     found = SearchOne( doc_fss->vRefNum, creator, app_fss );
  359.     
  360.     if (!found)
  361.         found = SearchAllButOne( 0, creator, doc_fss, app_fss );
  362.  
  363.     if (!found)
  364.         found = SearchAllButOne( 1, creator, doc_fss, app_fss );
  365. }
  366.  
  367. /* ======================================== */
  368.  
  369. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  370. {
  371.     FInfo    finfo;
  372.     FSSpec    app_fss;
  373.     FSSpec    doc_fss;
  374.     int        gotFSSpec;
  375.     int        result;
  376.     OSType    creator;
  377.     
  378.     nshc_parms->action = nsh_idle;        // always one pass to this command
  379.     gotFSSpec = fss_test();                // find out if fss is there
  380.     
  381.     // *** reason not to run 1 - bad included version
  382.     
  383.     if (nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION )) return;
  384.     
  385.     // *** reason not to run 2 - bad os version
  386.     
  387.     if ( Pre7() ) {
  388.         nshc_calls->NSH_putStr_err("\podoc: This command requires System 7.\r");
  389.         nshc_parms->result = NSHC_ERR_GENERAL;
  390.         return;
  391.         }
  392.         
  393.     // *** reason not to run 3 - bad parameters
  394.     
  395.     if (( nshc_parms->argc < 2 ) || ( nshc_parms->argc > 3 )) {
  396.         nshc_calls->NSH_putStr_err("\pUsage: odoc doc_path [app_path]\r");
  397.         nshc_parms->result = NSHC_ERR_PARMS;
  398.         return;
  399.         }
  400.         
  401.     // *** reason not to run 4 - can't find doc
  402.     
  403.     result = arg_to_fss( nshc_parms, nshc_calls, 1, &doc_fss );
  404.  
  405.     if (!result)
  406.         result = fss_GetFInfo( gotFSSpec, &doc_fss, &finfo );
  407.  
  408.     if (result) {
  409.         nshc_calls->NSH_putStr_err("\podoc: Document not found.\r");
  410.         nshc_parms->result = NSHC_ERR_PARMS;
  411.         return;
  412.         }
  413.         
  414.     creator = finfo.fdCreator;        // if nothing else, use doc's creator
  415.                     
  416.     // *** reason not to run 5 - can't find app
  417.     
  418.     if ( nshc_parms->argc > 2 ) {
  419.     
  420.         result = arg_to_fss( nshc_parms, nshc_calls, 2, &app_fss );
  421.         
  422.         if (!result)
  423.             result = fss_GetFInfo( gotFSSpec, &app_fss, &finfo );
  424.     
  425.         if (result || ( finfo.fdType != 'APPL' ) ) {
  426.             nshc_calls->NSH_putStr_err("\podoc: Application not found.\r");
  427.             nshc_parms->result = NSHC_ERR_PARMS;
  428.             return;
  429.             }
  430.             
  431.         creator = finfo.fdCreator;        // if available, use apps's creator
  432.                     
  433.         }
  434.         
  435.     // see if we should open or launch
  436.     
  437.     if (is_it_running( creator )) {
  438.         
  439.         // *** finally try to open the thing
  440.             
  441.         result = odoc( gotFSSpec, &doc_fss, creator, nshc_calls );
  442.  
  443.         }
  444.     
  445.     else {
  446.     
  447.         // *** or else try to launch it
  448.             
  449.         if ( nshc_parms->argc < 3 )
  450.             if ( !find_app( creator, &doc_fss, &app_fss ) ) {
  451.                 nshc_calls->NSH_putStr_err("\podoc: Document creator not found.\r");
  452.                 nshc_parms->result = NSHC_ERR_PARMS;
  453.                 return;
  454.                 }
  455.         
  456.         result = launch( gotFSSpec, &app_fss, &doc_fss, nshc_calls );
  457.  
  458.         }
  459.  
  460.     // *** log the result and return
  461.             
  462.     nshc_parms->result = result;
  463.  }
  464.